/*
 * File      : signal.h
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2017, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017/10/1      Bernard      The first version
 */
#include <rthw.h>
#include <rtthread.h>

#include <time.h>

#include "posix_signal.h"
#define sig_valid(sig_no)   (sig_no >= 0 && sig_no < RT_SIG_MAX)

void (*signal(int sig, void (*func)(int))) (int)
{
	return rt_signal_install(sig, func);
}

int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
{
	rt_base_t level;
    rt_thread_t tid;

    tid = rt_thread_self();

	level = rt_hw_interrupt_disable();
	if (oset) *oset = tid->sig_mask;

	if (set)
	{
		switch(how)
		{
		case SIG_BLOCK:
			tid->sig_mask |= *set;
			break;
		case SIG_UNBLOCK:
			tid->sig_mask &= ~*set;
			break;
		case SIG_SETMASK:
			tid->sig_mask =  *set;
			break;
		default:
			break;
		}
	}
	rt_hw_interrupt_enable(level);

    return 0;
}

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
    rt_sighandler_t old = RT_NULL;

	if (!sig_valid(signum)) return -RT_ERROR;

	if (act)
		old = rt_signal_install(signum, act->sa_handler);
	else
	{
		old = rt_signal_install(signum, RT_NULL);
		rt_signal_install(signum, old);
	}

	if (oldact)
		oldact->sa_handler = old;

    return 0;
}

int sigtimedwait(const sigset_t *set, siginfo_t *info,
       const struct timespec *timeout)
{
	return 0;
}

int sigwait(const sigset_t *set, int *sig)
{
    siginfo_t si;
    if (sigtimedwait(set, &si, 0) < 0)
        return -1;

    *sig = si.si_signo;
    return 0;
}

int sigwaitinfo(const sigset_t *set, siginfo_t *info)
{
  return sigtimedwait(set, info, NULL);
}

int raise(int sig)
{
	rt_thread_kill(rt_thread_self(), sig);
    return 0;
}

